/**
 * 定义一个接口，表示资源的结构。
 * 资源包含一个URL和可选的选项对象。
 */
interface IResource {
    url: string;
    options?: object;
}

/**
 * 定义一个接口，表示获取资源的功能。
 * 包含加载和卸载资源的方法。
 */
interface IFetchResource {
    load: (resource: IResource) => Promise<void>;
    unload: () => Promise<void>;
}

/**
 * 创建一个单例模式的函数，用于获取资源。
 * 该函数返回一个包含获取实例方法的对象。
 */
const fetchResourceSingleton = (function () {
    // 私有变量，用于存储单例实例
    let instance: IFetchResource;

    /**
     * 创建一个新的实例对象。
     * 该实例对象包含加载和卸载资源的方法。
     * @returns {IFetchResource} 返回一个新的实例对象
     */
    function createInstance() {
        return {
            /**
             * 加载资源的方法。
             * 该方法接受一个资源对象作为参数，并返回一个Promise。
             * @param {IResource} resource - 要加载的资源对象
             * @returns {Promise<void>} 返回一个Promise，表示资源加载完成
             */
            load: async (resource: IResource) => {
                const {url, options} = resource;
                return new Promise<void>(function (resolve, reject) {
                    // 创建一个script元素
                    const script = document.createElement('script');
                    script.type = 'text/javascript';
                    script.src = url;
                    // 如果有选项，则设置script元素的属性
                    if (options && Object.keys(options).length > 0) {
                        for (const key in options) {
                            script.setAttribute(key, options[key]);
                        }
                    }
                    // 当script加载完成时，调用resolve
                    script.onload = resolve as any;
                    // 当script加载失败时，调用reject
                    script.onerror = reject;
                    // 将script元素添加到文档中
                    document.body.appendChild(script);
                })
            },
            /**
             * 卸载资源的方法。
             * 该方法返回一个Promise，表示资源卸载完成。
             * @returns {Promise<void>} 返回一个Promise，表示资源卸载完成
             */
            unload: async () => {
                return Promise.resolve();
            }
        }
    }

    // 返回一个包含获取实例方法的对象
    return {
        /**
         * 获取单例实例的方法。
         * 如果实例不存在，则创建一个新的实例。
         * @returns {IFetchResource} 返回单例实例
         */
        getInstance: function () {
            if (!instance) {
                instance = createInstance();
            }
            return instance;
        }
    };
})();

// 导出单例实例
export const fetchResource = fetchResourceSingleton;
// 默认导出单例实例
export default fetchResourceSingleton;
